#pragma once 
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
#include <mysql/mysql.h>
#include "logger.hpp"
#include <vector>
#include <fstream>

class json_util{
public:
    //序列化
    static bool serialize(const Json::Value& value,std::string& str){
        std::stringstream ss;
        Json::StreamWriterBuilder swb;
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
        int ret=sw->write(value,&ss);
        if(ret!=0){
            ERR_LOG("serialize fail");
            return false;
        }
        str=ss.str();
        return true;
    }
    //反序列化
    static bool unserialize(const std::string& str,Json::Value& value){
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cb(crb.newCharReader());
        bool ret=cb->parse(str.c_str(),str.c_str()+str.size(),&value,nullptr);
        if(ret==false){
            ERR_LOG("unserialize fail");
            return false;
        }
        return true;
    }
};



class mysql_util{
public:
    //创建mysql句柄
    static MYSQL* mysql_create(
        const std::string& host,
        const std::string& user,
        const std::string passwd,
        const std::string& db,int port){
        //MySQL操作句柄初始化
        MYSQL* mysql=mysql_init(nullptr);
        if(mysql==nullptr){
            ERR_LOG("mysql_init fail");
            return nullptr;
        }
        //连接MySQL服务器
        if(mysql_real_connect(mysql,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,nullptr,0)==nullptr){
            ERR_LOG("mysql connect fail");
            return nullptr;
        }
        // 设置当前客⼾端的字符集
        int ret=mysql_set_character_set(mysql,"utf8");
        if(ret!=0){
            ERR_LOG("set character fail");
            return nullptr;
        }
        return mysql;
    }
    //关闭连接
    static void mysql_release(MYSQL* mysql){
        if(mysql==nullptr) return;
        mysql_close(mysql);
    }

    //执行sql语句
    static bool mysql_exec(MYSQL* mysql,const std::string& sql){
        if(mysql_query(mysql,sql.c_str())!=0){
            ERR_LOG("SQL:%s",sql.c_str());
            ERR_LOG("ERR:%s",mysql_error(mysql));
            return false;
        }
        return true;
    }
};


class string_util{
public:
    static int split(const std::string &in,const std::string& seq,std::vector<std::string>& array){
        int index=0,pos;
        while(index<in.size()){
            pos=in.find(seq,index);
            if(pos==std::string::npos){
                array.push_back(in.substr(index));
                break;
            }
            if(index==pos){
                index=pos+seq.size();
                continue;
            }
            if(pos-index>0)
                array.push_back(in.substr(index,pos-index));

            index=pos+seq.size();
        }
        return array.size();
    }
};


class file_util{
public:
    static bool read(const std::string& filename,std::string& body){
        std::ifstream file;
        //打开文件
        file.open(filename,std::ios::in | std::ios::binary);
        if(!file){
            ERR_LOG(" %s: open fail",filename.c_str());
            return false;
        }
        //获取文件大小
        //把文件指针移动到末尾
        file.seekg(0,std::ios::end);
        //获取当前位置偏移量并用它来给body开好空间
        body.resize(file.tellg());
        //让文件指针重新回到开始
        file.seekg(0,std::ios::beg);
        file.read(&body[0],body.size());
        if(file.good()==false){
            ERR_LOG("%s : Read failed!",filename);
            file.close();
            return false;
        }
        file.close();
        return true;
    }
};